﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using ShahyadS.TFSBuildInspectionModel;
using System.IO;
using ShahyadS.BuildInspectorVSPackage.Images;
using System.Drawing.Imaging;
using System.ComponentModel;
using Microsoft.TeamFoundation.Common;
using Microsoft.VisualStudio.TeamFoundation.Build;
using Microsoft.TeamFoundation.Build.Client;
using System.Diagnostics;
using Microsoft.VisualStudio.TeamFoundation;
using EnvDTE;
using System.Windows.Threading;
using ShahyadS.BuildInspectorVSPackage.Inspector;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition;
using ShahyadS.VisualStudio;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;

namespace ShahyadS.BuildInspectorVSPackage
{
	/// <summary>
	/// Interaction logic for TFSBuildInspectorWPFUserControl.xaml
	/// </summary>
	public partial class TFSBuildInspectorWPFUserControl : UserControl
	{
		CompositionContainer _container;
		[ImportMany]
		IEnumerable<Lazy<IVisualStudioAdapter, IVisualStudioAdapterData>> Adapters;
		IVisualStudioAdapter VisualStudioAdapter;
		public BuildDefinitionCollection BDC;
		BuildAgentCollection BAC;
		private void TfsExt_ProjectContextChanged(object sender, EventArgs e)
		{
			dynamic tfsExt = sender;
			Uri x = new Uri(tfsExt.ActiveProjectContext.DomainUri);
			if (!x.Equals(BDC.TeamProjectCollectionUrl))
			{
				BDC.TeamProjectCollectionUrl = x;
				BDC.AsyncRefresh();
				BAC.TeamProjectCollectionUrl = x;
			}
		}
		DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
		public object alaki;
		public TFSBuildInspectorWPFUserControl()
		{
			InitializeComponent();
			if (DesignerProperties.GetIsInDesignMode(this))
			{
				return;
			}
			string version = ((EnvDTE.DTE)ServiceProvider.GlobalProvider.GetService(typeof(EnvDTE.DTE).GUID)).Version;
			var catalog = new AggregateCatalog();
			var adaptersPath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(this.GetType().Assembly.Location), "Adapters");
			catalog.Catalogs.Add(new DirectoryCatalog(adaptersPath));
			_container = new CompositionContainer(catalog);
			try
			{
				_container.ComposeParts(this);
				VisualStudioAdapter = Adapters.Where(c => c.Metadata.Version == version).First().Value;
			}
			catch (Exception ex)
			{
				WriteLineToOutputWindow("Could not load Visual Studio Adapter.");
				WriteLineToOutputWindow(ex.Message);
				WriteLineToOutputWindow(ex.StackTrace);
			}
			BDC = new BuildDefinitionCollection();
			//this.DataContext = BDC;
			ListCollectionView collection = new ListCollectionView(BDC);
			collection.GroupDescriptions.Add(new PropertyGroupDescription("Extension"));
			collection.GroupDescriptions.Add(new PropertyGroupDescription("Line"));
			collection.SortDescriptions.Add(new SortDescription("Extension", ListSortDirection.Ascending));
			collection.SortDescriptions.Add(new SortDescription("Line", ListSortDirection.Ascending));
			collection.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));

			dataGrid1.ItemsSource = collection;

			BAC = new BuildAgentCollection();
			ListCollectionView agentCollection = new ListCollectionView(BAC);
			agentCollection.GroupDescriptions.Add(new PropertyGroupDescription("ControllerName"));
			agentCollection.SortDescriptions.Add(new SortDescription("ControllerName", ListSortDirection.Ascending));
			agentCollection.SortDescriptions.Add(new SortDescription("AgentName", ListSortDirection.Ascending));
			dataGrid2.ItemsSource = agentCollection;

			IVsExtensibility VsExtensibility = BuildInspectorVSPackagePackage.GetGlobalService(typeof(IVsExtensibility)) as IVsExtensibility;
			var dte = VsExtensibility.GetGlobalsObject(null).DTE;
			dynamic TfsExt = dte.GetObject("Microsoft.VisualStudio.TeamFoundation.TeamFoundationServerExt");
			if (!string.IsNullOrEmpty(TfsExt.ActiveProjectContext.DomainUri))
			{
				TfsExt_ProjectContextChanged(TfsExt, null);
			}
			TfsExt.ProjectContextChanged += new EventHandler(TfsExt_ProjectContextChanged);
			dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
			dispatcherTimer.Interval = new TimeSpan(0, 0, 15);
			dispatcherTimer.Start();
		}
		private void RefreshAllButton_Click(object sender, RoutedEventArgs e)
		{
			BDC.AsyncRefresh();
		}

		private void Window_Loaded(object sender, RoutedEventArgs e)
		{
		}
		void dispatcherTimer_Tick(object sender, EventArgs e)
		{
			RefreshAgents();
		}

		private void findInTeamExplorerMenuItem_Click(object sender, RoutedEventArgs e)
		{
			BuildDefinitionRow datarow = dataGrid1.CurrentItem as BuildDefinitionRow;
			VisualStudioAdapter.FindInTeamExplorer(datarow.TeamProject, datarow.BuildDefinitionName);
		}
		private void openBuildExplorerMenuItem_Click(object sender, RoutedEventArgs e)
		{
			BuildDefinitionRow datarow = dataGrid1.CurrentItem as BuildDefinitionRow;
			VisualStudioAdapter.OpenBuildExplorer(datarow.TeamProject, datarow.BuildDefinitionName);
		}

		private void editBuildDefinitionMenuItem_Click(object sender, RoutedEventArgs e)
		{
			BuildDefinitionRow datarow = dataGrid1.CurrentItem as BuildDefinitionRow;
			VisualStudioAdapter.EditBuildDefinition(datarow.BuildDefinitionUri);
		}

		private void queueNewBuildMenuItem_Click(object sender, RoutedEventArgs e)
		{
			BuildDefinitionRow datarow = dataGrid1.CurrentItem as BuildDefinitionRow;
			VisualStudioAdapter.QueueNewBuild(datarow.BuildDefinitionUri);
		}

		private void propertiesMenuItem_Click(object sender, RoutedEventArgs e)
		{

		}

		private void RefreshMenuItem_Click(object sender, RoutedEventArgs e)
		{
			var DataRows = new List<BuildDefinitionRow>();
			foreach (BuildDefinitionRow selectedRow in dataGrid1.SelectedItems)
			{
				DataRows.Add(selectedRow);
			}
			BDC.AsyncRefresh(DataRows);
		}

		private void selectallMenuItem_Click(object sender, RoutedEventArgs e)
		{

		}

		private void collapsAllMenuItem_Click(object sender, RoutedEventArgs e)
		{

		}

		private void expandAllMenuItem_Click(object sender, RoutedEventArgs e)
		{

		}

		private void excludeMenuItem_Click(object sender, RoutedEventArgs e)
		{
			var DataRows = new List<BuildDefinitionRow>();
			foreach (BuildDefinitionRow selectedRow in dataGrid1.SelectedItems)
			{
				DataRows.Add(selectedRow);
			}
			BDC.Exclude(DataRows);
		}

		private void openLatestBuildDetailMenuItem_Click(object sender, RoutedEventArgs e)
		{
			BuildDefinitionRow datarow = dataGrid1.CurrentItem as BuildDefinitionRow;
			if (datarow != null && !string.IsNullOrEmpty(datarow.LatestBuildDropLocation))
			{
				VisualStudioAdapter.OpenBuildDetail(datarow.LatestBuildUri);
			}
		}

		private void openDropLocation_Click(object sender, RoutedEventArgs e)
		{
			BuildDefinitionRow datarow = dataGrid1.CurrentItem as BuildDefinitionRow;
			if (datarow != null && !string.IsNullOrEmpty(datarow.LatestBuildDropLocation))
			{
				System.Diagnostics.Process prc = new System.Diagnostics.Process();
				prc.StartInfo.FileName = datarow.LatestBuildDropLocation;
				prc.Start();
			}
		}

		private void stopBuildMenuItem_Click(object sender, RoutedEventArgs e)
		{
			BuildDefinitionRow datarow = dataGrid1.CurrentItem as BuildDefinitionRow;
			if (datarow != null)
			{
				var queuedBuild = BDC.AllBuildInQueue.Where(q => q.BuildDefinition.Uri == datarow.BuildDefinitionUri).FirstOrDefault();
				if (queuedBuild != null)
				{
					if (queuedBuild.Status == QueueStatus.Queued || queuedBuild.Status == QueueStatus.Postponed)
					{
						queuedBuild.Cancel();
					}
					else if (queuedBuild.Status == QueueStatus.InProgress)
					{
						queuedBuild.Build.Stop();
					}
				}
			}
		}

		private void openCurrentBuildDetailMenuItem_Click(object sender, RoutedEventArgs e)
		{
			BuildDefinitionRow datarow = dataGrid1.CurrentItem as BuildDefinitionRow;
			if (datarow != null)
			{
				var queuedBuild = BDC.AllBuildInQueue.Where(q => q.BuildDefinition.Uri == datarow.BuildDefinitionUri).FirstOrDefault();
				if (queuedBuild != null && queuedBuild.Status == QueueStatus.InProgress)
				{
					VisualStudioAdapter.OpenBuildDetail(queuedBuild.Build.Uri);
				}
			}
		}

		private void ManageControllerButton_Click(object sender, RoutedEventArgs e)
		{
			VisualStudioAdapter.ShowControllerManager();
		}

		private void RefreshAllAgentsButton_Click(object sender, RoutedEventArgs e)
		{
			RefreshAgents();
		}
		private void RefreshAgents()
		{
			var refreshRequiredBuildDefinitions = BAC.Refresh();
			BDC.AsyncRefresh(BDC.Where(r => refreshRequiredBuildDefinitions.Contains(r.BuildDefinitionName)).ToList());
		}

		private void StatusIcon_ToolTipOpening(object sender, ToolTipEventArgs e)
		{
			System.Windows.Controls.Image img = (sender as System.Windows.Controls.Image);
			BuildDefinitionRow row = img.DataContext as BuildDefinitionRow;
			switch (row.Status)
			{
				case BuildDefinitionStatus.Ok:
					img.ToolTip = "Succeeded";
					break;
				case BuildDefinitionStatus.OkButQueue:
					img.ToolTip = "Succeeded but needed to queue new build";
					break;
				case BuildDefinitionStatus.OkIfDelete:
					img.ToolTip = "Succeeded but another build of the same source codes is failed and could be deleted";
					break;
				case BuildDefinitionStatus.Failed:
					img.ToolTip = "Failed";
					break;
				case BuildDefinitionStatus.Refreshing:
					img.ToolTip = "loading...";
					break;
				case BuildDefinitionStatus.Unknown:
					img.ToolTip = "Excluded";
					break;
				default:
					img.ToolTip = null;
					break;
			}
		}

		private void LatestBuildRetentionIcon_ToolTipOpening(object sender, ToolTipEventArgs e)
		{
			System.Windows.Controls.Image img = (sender as System.Windows.Controls.Image);
			BuildDefinitionRow row = img.DataContext as BuildDefinitionRow;
			switch (row.LatestBuildRetention)
			{
				case ExtendedBuildRetention.IsRetained:
					img.ToolTip = "Keep forever";
					break;
				case ExtendedBuildRetention.Refreshing:
					img.ToolTip = "loading...";
					break;
				case ExtendedBuildRetention.Unknown:
					img.ToolTip = "Excluded";
					break;
				default:
					img.ToolTip = null;
					break;
			}
		}

		private void LatestBuildReasonIcon_ToolTipOpening(object sender, ToolTipEventArgs e)
		{
			System.Windows.Controls.Image img = (sender as System.Windows.Controls.Image);
			BuildDefinitionRow row = img.DataContext as BuildDefinitionRow;
			switch (row.LatestBuildReason)
			{
				case ExtendedBuildReason.BatchedCI:
					img.ToolTip = "BatchedCI";
					break;
				case ExtendedBuildReason.Schedule:
					img.ToolTip = "Schedule";
					break;
				case ExtendedBuildReason.Refreshing:
					img.ToolTip = "loading...";
					break;
				case ExtendedBuildReason.Unknown:
					img.ToolTip = "Excluded";
					break;
				default:
					img.ToolTip = null;
					break;
			}
		}

		private void LatestBuildStatusIcon_ToolTipOpening(object sender, ToolTipEventArgs e)
		{
			System.Windows.Controls.Image img = (sender as System.Windows.Controls.Image);
			BuildDefinitionRow row = img.DataContext as BuildDefinitionRow;
			switch (row.LatestBuildStatus)
			{
				case ExtendedBuildStatus.Deleted:
					img.ToolTip = "the latest Build is Deleted";
					break;
				case ExtendedBuildStatus.Failed:
					img.ToolTip = "Failed at " + row.LatestBuildFinishTime;
					break;
				case ExtendedBuildStatus.InProgress:
					img.ToolTip = "InProgress";
					break;
				case ExtendedBuildStatus.NotStarted:
					img.ToolTip = "NotStarted";
					break;
				case ExtendedBuildStatus.PartiallySucceeded:
					img.ToolTip = "PartiallySucceeded at " + row.LatestBuildFinishTime;
					break;
				case ExtendedBuildStatus.Stopped:
					img.ToolTip = "Stopped at " + row.LatestBuildFinishTime;
					break;
				case ExtendedBuildStatus.Succeeded:
					img.ToolTip = "Succeeded at " + row.LatestBuildFinishTime;
					break;
				case ExtendedBuildStatus.Refreshing:
					img.ToolTip = "loading...";
					break;
				case ExtendedBuildStatus.Unknown:
					img.ToolTip = "Excluded";
					break;
				default:
					img.ToolTip = null;
					break;
			}
		}

		private void LatestBuildIsUpdatedIcon_ToolTipOpening(object sender, ToolTipEventArgs e)
		{
			System.Windows.Controls.Image img = (sender as System.Windows.Controls.Image);
			BuildDefinitionRow row = img.DataContext as BuildDefinitionRow;
			switch (row.LatestBuildIsUpdated)
			{
				case UpdateStatus.Updated:
					img.ToolTip = "Latest Source is built";
					break;
				case UpdateStatus.Outdated:
					img.ToolTip = "Sources are changed after the latest build. It needs to queue another build.";
					break;
				case UpdateStatus.Unknown:
					img.ToolTip = "Excluded";
					break;
				default:
					img.ToolTip = null;
					break;
			}
		}

		private void LatestGoodBuildIsUpdatedIcon_ToolTipOpening(object sender, ToolTipEventArgs e)
		{
			System.Windows.Controls.Image img = (sender as System.Windows.Controls.Image);
			BuildDefinitionRow row = img.DataContext as BuildDefinitionRow;
			switch (row.LatestGoodBuildIsUpdated)
			{
				case UpdateStatus.Updated:
					img.ToolTip = "Latest Source is built successfully";
					break;
				case UpdateStatus.Outdated:
					img.ToolTip = "Sources are changed after the latest Good build. It needs to queue another build.";
					break;
				case UpdateStatus.Refreshing:
					img.ToolTip = "loading...";
					break;
				case UpdateStatus.Unknown:
					img.ToolTip = "Excluded";
					break;
				default:
					img.ToolTip = null;
					break;
			}
		}

		private void LatestGoodBuildIsIntegratedIcon_ToolTipOpening(object sender, ToolTipEventArgs e)
		{
			System.Windows.Controls.Image img = (sender as System.Windows.Controls.Image);
			BuildDefinitionRow row = img.DataContext as BuildDefinitionRow;
			switch (row.LatestGoodBuildIsIntegrated)
			{
				case IntegrationStatus.Integrated:
					img.ToolTip = "is integrated with other related builds";
					break;
				case IntegrationStatus.NotIntegrated:
					img.ToolTip = "is not integrated with other related builds";
					break;
				case IntegrationStatus.Refreshing:
					img.ToolTip = "loading...";
					break;
				case IntegrationStatus.Unknown:
					img.ToolTip = "Excluded";
					break;
				default:
					img.ToolTip = null;
					break;
			}
		}

		private void CurrentBuildStatusIcon_ToolTipOpening(object sender, ToolTipEventArgs e)
		{
			System.Windows.Controls.Image img = (sender as System.Windows.Controls.Image);
			BuildDefinitionRow row = img.DataContext as BuildDefinitionRow;
			switch (row.CurrentBuildStatus)
			{
				case ExtendedBuildStatus.Deleted:
					img.ToolTip = "Deleted";
					break;
				case ExtendedBuildStatus.Failed:
					img.ToolTip = "Failed";
					break;
				case ExtendedBuildStatus.InProgress:
					img.ToolTip = "InProgress since " + row.QueuedBuild.Build.StartTime;
					break;
				case ExtendedBuildStatus.NotStarted:
					img.ToolTip = "Waiting for agent since" + row.QueuedBuild.QueueTime;
					break;
				case ExtendedBuildStatus.PartiallySucceeded:
					img.ToolTip = "PartiallySucceeded";
					break;
				case ExtendedBuildStatus.Stopped:
					img.ToolTip = "Stopped";
					break;
				case ExtendedBuildStatus.Succeeded:
					img.ToolTip = "Succeeded";
					break;
				case ExtendedBuildStatus.Refreshing:
					img.ToolTip = "loading...";
					break;
				case ExtendedBuildStatus.Unknown:
					img.ToolTip = "Excluded";
					break;
				default:
					img.ToolTip = null;
					break;
			}
		}
		private void includeButton_Click(object sender, RoutedEventArgs e)
		{
			new BuildDefinitionSelectionWindow(BDC).ShowDialog();
		}

		private void WriteLineToOutputWindow(string msg)
		{
			IVsOutputWindow outputWindow = BuildInspectorVSPackagePackage.GetGlobalService(typeof(SVsOutputWindow)) as IVsOutputWindow;
			Guid guidGeneral = Microsoft.VisualStudio.VSConstants.OutputWindowPaneGuid.GeneralPane_guid;
			IVsOutputWindowPane pane;
			int hr = outputWindow.CreatePane(guidGeneral, "BuildInspector", 1, 0);
			hr = outputWindow.GetPane(guidGeneral, out pane);
			pane.Activate();
			pane.OutputString("\n" + msg);
		}
	}
}
